<template>
    <div id="firefly"
         @mouseup="control($event,'up')"
         @mousemove="drag($event)"
         @mousedown="control($event,'down')"
         @touchend="control($event,'up')"
         @touchmove="drag($event)"
         @touchstart="control($event,'down')">
        <canvas :width="canvas.width" :height="canvas.height"></canvas>
    </div>
</template>

<script type="text/babel">
const {P, init} = require('../lib/Point');
const {Cube} = require('../lib/Cube');

var canvas = null;
var vm = null;

const scale = 1 / 50;
const w = 800;
const h = 800;
const focus = P(3000, 0, 0);
const f = 1000;
const starsMax = 50;
const CubeLength = 500;
const acc = 0.005;
const rMax = 500;

init({
    canvasWidth: w,
    canvasHeight: h,
    focalLength: f,
    focus: focus
});

var Box = new Cube(CubeLength);

//创造星云
var StarsCloud = [];
for (let i = 0; i < starsMax; i++) {
    StarsCloud.push(P(
            Math.floor(Math.random() * CubeLength - CubeLength / 2),
            Math.floor(Math.random() * CubeLength - CubeLength / 2),
            Math.floor(Math.random() * CubeLength - CubeLength / 2)
    ))
}

//根据顺序获取星星渲染时的参数
let getStarPorperty = (precent)=> {
    let Cmin = [104, 215, 137];
    let Cmax = [250, 255, 111];
    let Ccom = Cmin.map((c, i)=> {
        return Math.floor(-precent * (Cmax[i] - c)) + Cmax[i];
    });
    return {
        color: `rgba(${Ccom[0]},${Ccom[1]},${Ccom[2]},${-precent * 0.7 + 1})`
    }
};

function random(max,min=0){
    max = + max;
    min = + min;
    return min + Math.random()*(max-min);
}
window.random = random;

StarsCloud.forEach((p,i)=>{
    p.vx = random(100*acc,-100*acc);
    p.vy = random(100*acc,-100*acc);
    p.vz = random(100*acc,-100*acc);
})

const BeginAnimation = ()=>{
    setInterval(()=>{
        var {abs} = Math;
        var isOut = function(p){
            var m = rMax*rMax/4;
            return p.x*p.x>m||p.y*p.y>m||p.z*p.z>m;
        }

        StarsCloud.forEach((p,i)=>{
            p.ax = random(acc,-acc);
            p.ay = random(acc,-acc);
            p.az = random(acc,-acc);
            p.vx += p.ax;
            p.vy += p.ay;
            p.vz += p.az;

            if(isOut(p)){
                if(p.indicate==false){
                    p.reverse()
                };
                p.indicate = true;
            }else{
                p.indicate = false;
            }

            p.move();
        });
        vm.isChange = true;
    },30);
}

export default {
    data: ()=> ({
        isDrag: false,
        x: 0, y: 0,
        xa: 0, ya: 0,
        isChange: false,
        isPrevent: false,
        percent: 0,
        canvas: {
            width: `${w}px`,
            height: `${h}px`
        }
    }),
    methods: {
        spinX: function (a) {
            Box.vertexs.forEach((p)=> {
                p.turnX(a);
            });
            StarsCloud.forEach((p)=> {
                p.turnX(a);
            });
        },
        spinY: function (a) {
            Box.vertexs.forEach((p)=> {
                p.turnY(a);
            });
            StarsCloud.forEach((p)=> {
                p.turnY(a);
            });
        },
        draw: function () {
            canvas.clearRect(0, 0, w, h);
            canvas.fillStyle = "rgb(13,13,13)";
            canvas.fillRect(0, 0, 400, 400);

            Box.edges.sort((a, b)=> {
                return a.r < b.r
            }).forEach((edge, i)=> {
                let p1 = edge.a.toCanvas();
                let p2 = edge.b.toCanvas();
                let color = Math.floor(-(i / 11) * (20 - 30) + 30);

                canvas.strokeStyle = `rgb(${color},${color},${color})`;
                canvas.beginPath();
                canvas.moveTo(p1.x, p1.y);
                canvas.lineTo(p2.x, p2.y);
                canvas.closePath();
                canvas.stroke();
            });

            StarsCloud.sort((a, b)=>a.r > b.r);

            StarsCloud.forEach((p, i)=> {
                let canvasPoint = p.toCanvas();
                let star = getStarPorperty(i / starsMax);
                canvas.beginPath();
                canvas.arc(canvasPoint.x, canvasPoint.y, -i / starsMax + 2, 0, Math.PI * 2);
                canvas.closePath();
                if(p.indicate){
                    canvas.fillStyle = '#ff80c0';
                }else{
                    canvas.fillStyle = star.color;
                }
                canvas.fill();
            });

            canvas.shadowOffsetX = 0;
            canvas.shadowOffsetY = 0;
            canvas.shadowColor = 'rgba(255,255,255,0.5)';
            canvas.shadowBlur = 0;

        },
        drag: function ($event) {
            $event.preventDefault();
            if (!this.isDrag || this.isPrevent)return;
            let {abs} = Math;
            let dx = ($event.clientX || $event.touches[0].clientX) - this.x;
            let dy = ($event.clientY || $event.touches[0].clientY) - this.y;
            if (abs(dx) > 0) {
                this.spinX(dx * scale);
            }
            if (abs(dy) > 0) {
                this.spinY(dy * scale);
            }
            this.isChange = true;
            this.x = $event.clientX || $event.touches[0].clientX;
            this.y = $event.clientY || $event.touches[0].clientY;
        },
        control: function ($event, event) {
            if (event == 'down') {
                this.isDrag = true;
                this.x = $event.clientX || $event.touches[0].clientX;
                this.y = $event.clientY || $event.touches[0].clientY;
            } else if (event == 'up') {
                this.isDrag = false;
            }
        }
    },
    ready: function () {
        canvas = [...this.$el.children].filter((n)=> {
            return n.localName == 'canvas'
        })[0].getContext('2d');
        window.canvas = canvas;
        this.isChange = true;

        vm = this;
        BeginAnimation();

        let Render = ()=> {
            if (!vm.isChange) {
                return window.AnimeRender(Render);
            } else {
                vm.draw();
                vm.isChange = false;
                window.AnimeRender(Render);
            }
        };
        window.AnimeRender(Render);
    },
}
</script>
